<?php

class Application_Model_GroupMapper {

    protected $_dbTable;

    public function setDbTable($dbTable) {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }

    public function getDbTable() {
        if (null === $this->_dbTable) {
            $this->setDbTable('Application_Model_DbTable_Group');
        }
        return $this->_dbTable;
    }

    public function save(Application_Model_Group $group) {
        $data = array(
            'id' => $group->id(),
            'name' => $group->name(),
            'categorizing' => $group->categorizing(),
            'image_id' => $group->image_id(),
            'description' => $group->description(),
            'owner_id' => $group->owner_id(),
        );
        if (null === ($id = $group->id())) {
            unset($data['id']);
            return $this->getDbTable()->insert($data);
        } else {
            $this->getDbTable()->update($data, array('id = ?' => $id));
            return $id;
        }
    }

    public function find($id) {
        $result = $this->getDbTable()->find($id);
        if (0 == count($result)) {
            return null;
        }
        $row = $result->current();
        return new Application_Model_Group($row->id, $row->name, $row->categorizing, $row->image_id, $row->description, $row->owner_id);
    }

    public function is_user_subscribed($uid, $gid) {
        $subdb = new Application_Model_DbTable_Subscription();
        $rowset = $subdb->find($uid, $gid);
        if ($rowset->count() > 0) {
            return true;
        }
        return false;
    }

    public function add_subscription($gid, $uid) {
        $subdb = new Application_Model_DbTable_Subscription();
        return $subdb->insert(array("user_id" => $uid, "group_id" => $gid));
    }

    public function del_subscription($gid, $uid) {
        $subdb = new Application_Model_DbTable_Subscription();
        return $subdb->delete("user_id=$uid AND group_id=$gid");
    }

    public function findSubscribedGroups($uid) {
        $utable = new Application_Model_DbTable_User();
        $rows = $utable->find($uid)->current()->findManyToManyRowset('Application_Model_DbTable_Group', 'Application_Model_DbTable_Subscription');
        $entries = array();
        foreach ($rows as $row) {
            $entry = new Application_Model_Group($row->id, $row->name, $row->categorizing, $row->image_id, $row->description, $row->owner_id);
            $entries[] = $entry;
        }
        return $entries;
    }

    public function find_element_list($gid, $filter = "id DESC") {
        $rowset = $this->getDbTable()->find($gid);
        if (0 == count($rowset)) {
            return null;
        }
        $row = $rowset->current();
        $elem_rowset = $row->findManyToManyRowset("Application_Model_DbTable_Element", "Application_Model_DbTable_GroupElement");
        if ($elem_rowset) {
            $result = array();
            foreach ($elem_rowset as $el_row) {
                $result[] = new Application_Model_Element($el_row->id, $el_row->name,
                                $el_row->tech_id, $el_row->total_size, $el_row->available_size,
                                $el_row->owner_id, $el_row->status, $el_row->tracker, $el_row->type);
            }
            $result = $this->orderBy($result, $filter);
            return $result;
        } else {
            return null;
        }
    }

    private function orderBy($arr, $filter) {
        if ($filter == "name ASC") {
            $fn = create_function('$el1, $el2', 'return strcmp($el1->name(), $el2->name());');
        } elseif ($filter == "name DESC") {
            $fn = create_function('$el1, $el2', 'return strcmp($el2->name(), $el1->name());');
        } elseif ($filter == "id ASC") {
            $fn = create_function('$el1, $el2', 'return $el1->id() - $el2->id();');
        } else {
            $fn = create_function('$el1, $el2', 'return $el2->id() - $el1->id();');
        }
        usort($arr, $fn);
        return $arr;
    }

    public function fetchAll($order = "name ASC") {
        $resultSet = $this->getDbTable()->fetchAll(null, $order);
        $entries = array();
        foreach ($resultSet as $row) {
            $entry = new Application_Model_Group($row->id, $row->name, $row->categorizing, $row->image_id, $row->description, $row->owner_id);
            $entries[] = $entry;
        }
        return $entries;
    }

    public function findAllCategorizing() {
        $rowset = $this->getDbTable()->fetchAll("categorizing = 1", "name");
        foreach ($rowset as $row) {
            $entry = new Application_Model_Group($row->id, $row->name, $row->categorizing, $row->image_id, $row->description, $row->owner_id);
            $entries[] = $entry;
        }
        return $entries;
    }

    public function findLinkedGroups(Application_Model_Element $element) {
        $elementMapper = new Application_Model_ElementMapper();
        $elemrow = $elementMapper->getDbTable()->find($element->id())->current();
        $rowset = $elemrow->findManyToManyRowset("Application_Model_DbTable_Group", "Application_Model_DbTable_GroupElement");
        $entries = array();
        foreach ($rowset as $row) {
            $entry = new Application_Model_Group($row->id, $row->name, $row->categorizing, $row->image_id, $row->description, $row->owner_id);
            $entries[] = $entry;
        }
        /*usort($entries, create_function('$el1, $el2',
            'if ($el1->categorizing() && !$el2->categorizing()) { return 1; ' .
            '} else { return strcmp($el1->name(), $el2->name()); }'));*/
        return $entries;
    }

    public function remove($id) {
        return $this->getDbTable()->delete("id=$id");
    }

    public function findLinkedComments($id) {
        $rowset = $this->getDbTable()->find($id);
        if (0 == count($rowset)) {
            return null;
        }
        $row = $rowset->current();
        $comment_rowset = $row->findManyToManyRowset("Application_Model_DbTable_Comment", "Application_Model_DbTable_CommentLink");
        if ($comment_rowset) {
            $umapper = new Application_Model_UserMapper();
            $result = array();
            foreach ($comment_rowset as $row) {
                $entry = new Application_Model_Comment($row->id, $row->user_id, $row->time, $row->content);
                $entry->set_user($umapper->find($entry->user_id()));
                $result[] = $entry;
            }
            usort($result, create_function('$comment1, $comment2', 'return $comment1->time() - $comment2->time();'));
            return $result;
        } else {
            return null;
        }
    }
}
